package core

import (
	"sync"
	"encoding/json"
	"errors"
	"go-iot/app/iot/eventbus"
	"go-iot/app/iot/eventbus/message"
)

const (
	ONLINE   = "online"   // 在线
	OFFLINE  = "offline"  // 离线
	NoActive = "noActive" // 未启用
	DEVICE    = "device"    // 设备
	GATEWAY   = "gateway"   // 网关
	SUBDEVICE = "subdevice" // 子设备
)

// 函数没有实现
var ErrFunctionNotImpl = errors.New("function not impl")
var deviceLifeCycleMap sync.Map

type (
	
	DeviceLifecycle interface {
		// 设备发布
		OnDeviceDeploy(ctx DeviceLifecycleContext) error
		// 设备取消发布
		OnDeviceUnDeploy(ctx DeviceLifecycleContext) error
		// 设备状态检查
		OnStateChecker(ctx DeviceLifecycleContext) (string, error)
	}

	// 消息上下文
	MessageContext interface {
		DeviceLifecycleContext
		GetMessage() interface{}
		GetSession() Session
	}
	//  设备生命周期上下文
	DeviceLifecycleContext interface {
		// 获取设备操作
		GetDevice() *Device
		// 获取产品操作
		GetProduct() *Product
	}
)

// 编辑码器配置，有些编辑码需要提供一些默认的配置这样产品添加时就不需要手动加配置
type CodecMetaConfig struct {
	MetaConfigs []MetaConfig
	CodecId     string
}

func (p CodecMetaConfig) ToJson() string {
	b, _ := json.Marshal(p.MetaConfigs)
	return string(b)
}

// 元数据配置结构
type MetaConfig struct {
	Property string `json:"property,omitempty"`
	Type     string `json:"type,omitempty"`
	Value    string `json:"value,omitempty"`
	Buildin  bool   `json:"buildin,omitempty"`
	Desc     string `json:"desc,omitempty"`
}

// device lifecycle
func RegDeviceLifeCycle(productId string, liefcycle DeviceLifecycle) {
	// val, ok := deviceLifeCycleMap.Load(productId)
	// if val == nil || !ok {
	deviceLifeCycleMap.Store(productId, liefcycle)
	// }
}

func GetDeviceLifeCycle(productId string) DeviceLifecycle {
	val, ok := deviceLifeCycleMap.Load(productId)
	if val != nil && ok {
		v := val.(DeviceLifecycle)
		return v
	}
	return nil
}

// 获取设备状态，当设备有session时返回online, 否则调用OnStateChecker方法来查询
func GetDeviceState(deviceId, productId string) string {
	sess := GetSession(deviceId)
	if sess != nil {
		return ONLINE
	} else {
		liefcycle := GetDeviceLifeCycle(productId)
		if liefcycle != nil {
			state, err := liefcycle.OnStateChecker(&BaseContext{
				ProductId: productId,
				DeviceId:  deviceId,
			})
			if err == nil && state == ONLINE {
				return ONLINE
			}
		}
	}
	return OFFLINE
}

// 设备发布
func OnDeviceDeploy(device *Device) error {
	liefcycle := GetDeviceLifeCycle(device.ProductId)
	if liefcycle != nil {
		var deviceId = device.Id
		err := liefcycle.OnDeviceDeploy(&BaseContext{
			ProductId: device.ProductId,
			DeviceId:  deviceId,
			device:    device,
		})
		if err != ErrFunctionNotImpl {
			return err
		}
	}
	return nil
}

// 设备取消发布
func OnDeviceUnDeploy(device *Device) error {
	liefcycle := GetDeviceLifeCycle(device.ProductId)
	if liefcycle != nil {
		var deviceId = device.Id
		err := liefcycle.OnDeviceUnDeploy(&BaseContext{
			ProductId: device.ProductId,
			DeviceId:  deviceId,
			device:    device,
		})
		if err != ErrFunctionNotImpl {
			return err
		}
	}
	return nil
}


// 调试日志
func DebugLog(deviceId, productId string, v string) {
	if deviceId == "" {
		deviceId = "-"
	}
	eventbus.PublishDebug(message.NewDebugMessage(deviceId, productId, v))
}